package web.utils;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;

import cnki.tpi.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import org.apache.commons.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.DigestUtils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @author cb
 * @Description TODO
 * @date 2023/9/19
 */
public class AesEncryptUtil {


    /***
     * key和iv值可以随机生成
     */
    private static String KEY = "1234567890123456";
    private static String IV = "1234567890123456";




    /***
     * 加密
     * @param  data 要加密的数据
     * @return encrypt
     */
    public static String encrypt(String data){
        return encrypt(data, KEY, IV);
    }
    /***
     * param data 需要解密的数据
     * 调用desEncrypt（）方法
     */
    public static String desEncrypt(String data){
        return desEncrypt(data, KEY, IV);
    }
    /**
     * 加密方法
     * @param data  要加密的数据
     * @param key 加密key
     * @param iv 加密iv
     * @return 加密的结果
     */
    private static String encrypt(String data, String key, String iv){
        try {
            //"算法/模式/补码方式"NoPadding PkcsPadding
            Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
            int blockSize = cipher.getBlockSize();
            byte[] dataBytes = data.getBytes();
            int plaintextLength = dataBytes.length;
            if (plaintextLength % blockSize != 0) {
                plaintextLength = plaintextLength + (blockSize - (plaintextLength % blockSize));
            }
            byte[] plaintext = new byte[plaintextLength];
            System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length);
            SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
            IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());
            cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
            byte[] encrypted = cipher.doFinal(plaintext);
            return new Base64().encodeToString(encrypted);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
    /**
     * 解密方法
     * @param data 要解密的数据
     * @param key  解密key
     * @param iv 解密iv
     * @return 解密的结果
     */
    private static String desEncrypt(String data, String key, String iv){
        try {
            byte[] encrypted1 = new Base64().decode(data);
            Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
            SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "AES");
            IvParameterSpec ivSpec = new IvParameterSpec(iv.getBytes());
            cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
            byte[] original = cipher.doFinal(encrypted1);
            return new String(original).trim();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
    /**
     * MD5 加密 DigestUtils 是 org.apache.commons.codec.digest.DigestUtils 的工具类，springboot提供
     *
     * @param str 被加密的字符串
     * @return: java.lang.String
     */
    public static String encryption(String str, Long time) throws UnsupportedEncodingException {
        String s = URLEncoder.encode((str + time), "utf-8").toLowerCase(Locale.ROOT);
        return DigestUtils.md5DigestAsHex(s.getBytes(StandardCharsets.UTF_8));
    }

    // 解析 get 请求参数，并生成 map
    public static Map<String, Object> parseGetRequest(HttpServletRequest request) {
        Map<String, Object> map = new LinkedHashMap<>();
        Enumeration<String> parameterNames = request.getParameterNames();
        while (parameterNames.hasMoreElements()) {
            String element = parameterNames.nextElement();
            map.put(element, request.getParameter(element));
        }
        return map;
    }

    // 解析 post 请求参数，并生成 map
    public static Map<String, Object> parsePostRequest(HttpServletRequest req) throws IOException {
        BufferedReader bufferReaderBody= new BufferedReader(req.getReader());
        return JSON.parseObject(Optional.ofNullable(bufferReaderBody.readLine()).orElse("{}"));
    }


    /**
     * 请求检验
     */
    public static String checkToken(String token, String time, Map<String, Object> map) throws IOException {
        if (StrUtil.checkStringNull(time) && StrUtil.checkStringNull(token)) {

            // 判断请求是否超时
            long l = Long.parseLong(time);
            // 10分钟 方便测试
            // 升序排序 json 对象
            String encryption = encryption(JSON.toJSONString(map, SerializerFeature.MapSortField), l);
            // 判断是否篡改数据
              return  encryption;
        }
        return "";
    }



}
